#ifndef __OXML_ITEM_CACHE_H__
#define __OXML_ITEM_CACHE_H__
#include "const/oPreDefine.h"
#include "misc/oContent.h"

#define SHARED_CACHE_FUNC(name) public: static name& sharedCache(){ static name instance;return instance; }

/** @brief Useful for reading xml files and cache them in memory.
 T is the class to store every parsed xml file.
*/
template<class T>
class oXmlItemCache: public CCSAXDelegator
{
	typedef typename hash_strmap<T*>::iterator hash_strmap_iter;
public:
	~oXmlItemCache()
	{
		oXmlItemCache::unload();
	}
	/** Load a new xml file or get its data for cache. */
	T* load( const char* filename )
	{
		hash_strmap_iter it = _dict.find(filename);
		if (it != _dict.end())
		{
			return it->second;
		}
		else
		{
			this->beforeParse(filename);
			unsigned long size;
			char* data = oSharedContent.loadFile(filename, size);
			_parser.parseData(data, size);
			delete [] data;
			this->afterParse(filename);
			_dict[filename] = _item;
			return _item;
		}
	}
	/** Purge the cached file. */
	bool unload( const char* filename )
	{
		hash_strmap_iter it = _dict.find(filename);
		if (it != _dict.end())
		{
			it->second->release();
			_dict.erase(it);
			return true;
		}
		return false;
	}
	/** Purge all cached files. */
	void unload()
	{
		if (_dict.size() > 0)
		{
			hash_strmap_iter it = _dict.begin();
			for (;it != _dict.end();it++)
			{
				it->second->release();
			}
			_dict.clear();
		}
	}
protected:
	oXmlItemCache():_item(nullptr)
	{
		_parser.setDelegator(this);
	}
	hash_strmap<T*> _dict;
	T* _item;
private:
	CCSAXParser _parser;
	/** Implement it to get prepare for specific xml parse. */
	virtual void beforeParse( const char* filename ) = 0;
	/** Implement it to do something after xml is parsed. */
	virtual void afterParse( const char* filename ) = 0;
	/** Implement it to parse xml. Google SaxParser */
	virtual void textHandler( void *ctx, const char *s, int len ) = 0;
	/** Implement it to parse xml. Google SaxParser */
	virtual void startElement( void *ctx, const char *name, const char **atts ) = 0;
	/** Implement it to parse xml. Google SaxParser */
	virtual void endElement( void *ctx, const char *name ) = 0;
};

#endif